/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2017 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/

//***********************************************************************************************************
//  Nuvoton Technoledge Corp. 
//  Website: http://www.nuvoton.com
//  E-Mail : MicroC-8bit@nuvoton.com
//  Date   : Jun/21/2017
//***********************************************************************************************************

//***********************************************************************************************************
//  File Function: N76E003 I2C demo code, Slave Address of 24LC64 = 0xA0
//
//   ____________           ______________ 
//  |            |   SDA    |             |
//  |            |<-------->|             |
//  |            |          |             |
//  |N76E003(M) |          |   24LC64(S) |
//  |            |   SCL    |             |
//  |            |--------->|             |
//  |____________|          |_____________|
//
//  Microchip I2C EEPROM 24xx64 (64K Bit) is used as the slave device.  
//  The page size are 32Byte. Total are 256 page.
//  If verification passes, Port3 will show 0x78. If there is any failure
//  occured during the progress, Port3 will show 0x00.
//***********************************************************************************************************

#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"

#define SOFT_IIC

#define SYS_CLK_EN              0
#define SYS_SEL                 2
#define SYS_DIV_EN              0                   //0: Fsys=Fosc, 1: Fsys = Fosc/(2*CKDIV)
#define SYS_DIV                 1
#define I2C_CLOCK               49

#define AM2320SLA              0xB8
#define AM2320WR                0
#define AM2320RD                1

#define LED                     P3
#define PAGE_SIZE               32
#define PAGE_NUMBER             4

#define ERROR_CODE              0x78
#define TEST_OK                 0x00
  
#define IIC_SDA                SDA
#define IIC_SCL                SCL

bit I2C_Reset_Flag;

UINT8 AM2320Data[10];
//========================================================================================================
void Init_I2C(void)
{
	P13_OpenDrain_Mode;					// Modify SCL pin to Open drain mode. don't forget the pull high resister in circuit
	P14_OpenDrain_Mode;					// Modify SDA pin to Open drain mode. don't forget the pull high resister in circuit
#ifdef SOFT_IIC
	SDA = 1;
	SCL = 1;
#else 
    /* Set I2C clock rate */
    I2CLK = I2C_CLOCK; 

    /* Enable I2C */
    set_I2CEN;
#endif
}

//========================================================================================================
#ifdef SOFT_IIC
void delay_us(UINT8 cnt)
{
	UINT8 i;
	for(i=0;i<cnt;i++){
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
		nop;
	}
}
//开始信号
void I2C_Start()
{
	IIC_SCL=1;
	IIC_SDA=1;
	delay_us(4);
	IIC_SDA=0;
	delay_us(4);
	IIC_SCL=0;//结束后SDA=0，SCL=0
}
//停止信号
void I2C_Stop()
{		
	IIC_SDA=0;
	delay_us(4);
	IIC_SCL=1;
	delay_us(4);
	IIC_SDA=1;
	delay_us(4);//结束后SDA=1，SCL=1
}
//MCU给从机应答信号
void MCU_SendAck()
{	
	IIC_SDA=0;
	delay_us(4);
	IIC_SCL=1;
	delay_us(4);
	IIC_SCL=0;
	delay_us(1);
	IIC_SDA=1;	 //结束后SDA=1，SCL=0
	delay_us(4);
}
//MCU给从机非应答信号
void MCU_SendNack()
{	
	IIC_SDA=1;
	delay_us(4);
	IIC_SCL=1;
	delay_us(4);
	IIC_SCL=0;
	delay_us(1);
	IIC_SDA=1; //结束后SDA=1，SCL=0
	delay_us(4);
}
//MCU检查从机发来的应答信号
void MCU_CheckAck()
{	
	UINT8 ucErrTime=0;
	IIC_SDA=1;//拉高SDA
	/* SDA_IN; */
	P14_Input_Mode;
	delay_us(4);
	IIC_SCL=1;
	/* while(READ_SDA)	 //等待应答信号 */
	while(SDA)	 //等待应答信号
	{	
		ucErrTime++;
		if(ucErrTime>250) //等待250个循环周期，如果未收到应答信号则直接发送停止信号给从机
		{
			/* I2C_Stop(); */
			break;
		}
	}
	delay_us(4);
	IIC_SCL=0;
	/* SDA_OUT;   //结束后SDA=1，SCL=0 */
	P14_OpenDrain_Mode;
}
//MCU往IIC总线传送一字节数据
void I2C_W_byte(UINT8 dat)
{
	UINT8 i;
	for(i=0;i<8;i++)
	{		
		if((dat&0x80)>>7)
			IIC_SDA=1;
		else
			IIC_SDA=0;
		dat<<=1;
		delay_us(4); //为ATCxx而设的时间间隔
		IIC_SCL=1;
		delay_us(4); //为ATCxx而设的时间间隔
		IIC_SCL=0;//与IIC_SCL=1配对
	}				   //结束后SDA=?，SCL=0
}
//MCU从IIC总线接收一字节数据
UINT8 I2C_R_byte()
{
	UINT8 i,tmp;
	/* SDA_IN; */
	P14_Input_Mode;
	for(i=0;i<8;i++)
	{	
	 	tmp<<=1;
//		tmp|=READ_SDA; 
		delay_us(4); //为ATCxx而设的时间间隔	
		IIC_SCL=1;
		delay_us(4); //为ATCxx而设的时间间隔
		IIC_SCL=0;
		/* tmp|=READ_SDA; //放前面和后面效果一样 */
		tmp|=SDA; //放前面和后面效果一样
	}				 //结束后SDA=?，SCL=0
	/* SDA_OUT; */
	P14_OpenDrain_Mode;
	return tmp;	
}
#endif

void AM2320_Wakeup()
{
	I2C_Start();
	I2C_W_byte(AM2320SLA+AM2320WR);
	MCU_CheckAck();
	Timer0_Delay1ms(1);
	I2C_Stop();
}

void AM2320_ReadData()
{
	I2C_Start();
	I2C_W_byte(AM2320SLA+AM2320WR);
	MCU_CheckAck();
	I2C_W_byte(0x03);
	MCU_CheckAck();
	I2C_W_byte(0x00);
	MCU_CheckAck();
	I2C_W_byte(0x04);
	MCU_CheckAck();
	I2C_Stop();
	Timer0_Delay1ms(2);
	I2C_Start();
	I2C_W_byte(AM2320SLA+AM2320RD);
	MCU_CheckAck();
	Timer0_Delay100us(1);
	AM2320Data[0] = I2C_R_byte();   //返回应该是0x03
	MCU_SendAck();
	AM2320Data[1] = I2C_R_byte();   //返回应该是0x04
	MCU_SendAck();
	AM2320Data[2] = I2C_R_byte();   //返回的温湿度值，总共4字节
	MCU_SendAck();
	AM2320Data[3] = I2C_R_byte();
	MCU_SendAck();
	AM2320Data[4] = I2C_R_byte();
	MCU_SendAck();
	AM2320Data[5] = I2C_R_byte();
	MCU_SendAck();
	AM2320Data[6] = I2C_R_byte();   //返回的CRC值
	MCU_SendAck();
	AM2320Data[7] = I2C_R_byte();   //返回的CRC值
	MCU_SendNack();
	I2C_Stop();
	MCU_SendAck();
}

UINT16 crc16(UINT8 *ptr, UINT8 len)
{
	UINT16 crc=0xFFFF;
	UINT8 i;
	while(len--) {
		crc ^=*ptr++;
		for(i=0;i<8;i++){
			if(crc & 0x01) {
				crc>>=1;
				crc^=0xA001;
			}else{
				crc>>=1;
			}
		}
	}
	return crc;
}

void main(void)
{
	UINT16 crc;
	UINT8  sent_temper_val[7];
	UINT8  sent_humi_val[7];

    Set_All_GPIO_Quasi_Mode;
	InitialUART0_Timer3(9600);
	P12_PushPull_Mode;
	P05_PushPull_Mode;
	P05 = 1;
    /* Initial I2C function */
    Init_I2C();                                 //initial I2C circuit
    

    while (1){
		clr_GPIO1;
		Timer0_Delay1ms(500);
		AM2320_Wakeup();
		Timer0_Delay1ms(1);
		//
		AM2320_ReadData();
		/* Timer0_Delay1ms(2500); */
		/* AM2320_ReadData(); */
		set_GPIO1;
		/* Send_Data_To_UART0(AM2320Data[0]); */
		/* Send_Data_To_UART0(AM2320Data[1]); */
		/* Send_Data_To_UART0(AM2320Data[2]); */
		/* Send_Data_To_UART0(AM2320Data[3]); */
		/* Send_Data_To_UART0(AM2320Data[4]); */
		/* Send_Data_To_UART0(AM2320Data[5]); */
		/* Send_Data_To_UART0(AM2320Data[6]); */
		/* Send_Data_To_UART0(AM2320Data[7]); */
		if((AM2320Data[0]==0x03) && (AM2320Data[1]==0x04)){
			sent_temper_val[0] = 0x02;  //device addr
			sent_temper_val[1] = 0x03;  //read cmd
			sent_temper_val[2] = 0x02;  //read bytes
			sent_temper_val[3] = AM2320Data[4];
			sent_temper_val[4] = AM2320Data[5];
			crc = crc16(sent_temper_val,5);
			sent_temper_val[5] = crc>>8;
			sent_temper_val[6] = crc & 0xff;
			Send_Data_To_UART0(sent_temper_val[0]);
			Send_Data_To_UART0(sent_temper_val[1]);
			Send_Data_To_UART0(sent_temper_val[2]);
			Send_Data_To_UART0(sent_temper_val[3]);
			Send_Data_To_UART0(sent_temper_val[4]);
			Send_Data_To_UART0(sent_temper_val[5]);
			Send_Data_To_UART0(sent_temper_val[6]);
			Timer0_Delay1ms(1000);
			sent_humi_val[0] = 0x03;  //device addr
			sent_humi_val[1] = 0x03;  //read cmd
			sent_humi_val[2] = 0x02;  //read bytes
			sent_humi_val[3] = AM2320Data[2];
			sent_humi_val[4] = AM2320Data[3];
			crc = crc16(sent_humi_val,5);
			sent_humi_val[5] = crc>>8;
			sent_humi_val[6] = crc & 0xff;
			Send_Data_To_UART0(sent_humi_val[0]);
			Send_Data_To_UART0(sent_humi_val[1]);
			Send_Data_To_UART0(sent_humi_val[2]);
			Send_Data_To_UART0(sent_humi_val[3]);
			Send_Data_To_UART0(sent_humi_val[4]);
			Send_Data_To_UART0(sent_humi_val[5]);
			Send_Data_To_UART0(sent_humi_val[6]);
		}
		/* Send_Data_To_UART0(crc&0xFF); */
		/* Send_Data_To_UART0(crc>>8); */
		/* if(crc !=  (AM2320Data[6]|(AM2320Data[7]<<8))){ */
		/*     Send_Data_To_UART0(255); */
		/* }else{ */
		/*     Send_Data_To_UART0(0); */
		/* } */
		Timer0_Delay1ms(5000);
	}
/* =================== */
}

